/*
 ============================================================================
 Name        : tp5.c
 Author      : Pablo Henrique dos Reis
 Description : Trabalho prático 5 - Localidade de Referência
 ============================================================================
 */

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

#include "analisador.h"
#include "entradaSaida.h"

#define LEITURA "r"
#define ESCRITA "w"

#define MAX_LINHA 30
#define MAX_BUFFER 10
#define MAX_VIDEOS 30

/**
 * Extrai numeros separados por espaço de uma string
 */
long *extrairNumeros(char *str, int qtd) {

	long *retorno  = (long*)malloc(sizeof(long)*qtd);
	int indice = 0;
	char * pch = (char*) strtok(str, " ");

	while (pch != NULL) {
		long inteiro = atoi(pch);
		retorno[indice] = inteiro;

		indice++;
		pch = (char *) strtok(NULL, " ");
	}

	return retorno;
}

void preencherChunks(ListaChunk *l, char *nomeArquivo) {

	FILE *arq = NULL;
	abrirArquivo(&arq, nomeArquivo, LEITURA);
	char buffer[MAX_LINHA];

	while(lerLinha(buffer, MAX_LINHA, &arq) != NULL) {
		long *dados = extrairNumeros(buffer,3);
		long idVideo = dados[0];
		long indiceChunk = dados[1];
		long tamanhoChunk = dados[2];
		free(dados);
		inserirChunk(l,idVideo, indiceChunk, tamanhoChunk, -1);
	}
	fecharArquivo(&arq);
}

void obterLocalidadeEspacial(FILE **arq, ListaChunk *L) {

	ListaString listaTexto[MAX_VIDEOS];
	PChunk aux = L->Primeiro->prox;
	int videos[MAX_VIDEOS];
	int i;
	int prim = 1;

	for(i=0;i<MAX_VIDEOS;i++) videos[i] = -1;

	while(aux != NULL) {
		char *buffer = (char*) malloc(sizeof(char)*MAX_BUFFER);
		int idVideo = aux->itemChunk.idVideo;
		int distancia = 0;

		if(videos[idVideo] == -1) {
			criarListaString(&listaTexto[idVideo]);
			if(prim)
				inserirItemString(&listaTexto[idVideo], "0");
			else
				inserirItemString(&listaTexto[idVideo], ",0");
			videos[idVideo] = aux->itemChunk.indiceChunk;
		} else {
			distancia = aux->itemChunk.indiceChunk - videos[idVideo];
			if(distancia < 0) distancia *= -1;
			snprintf(buffer,MAX_BUFFER, ",%d", distancia);
			inserirItemString(&listaTexto[idVideo], buffer);
			videos[idVideo] = aux->itemChunk.indiceChunk;
		}
		aux = aux->prox;
		prim = 0;
	}

	for(i=0;i<MAX_VIDEOS;i++) {
		if(videos[i] != -1) {
			if(!isListaStringVazia(listaTexto[i])) {
				PItemString aux = listaTexto[i].Primeiro->prox;
				while (aux != NULL)
				{
					escreverNoArquivo(arq,aux->texto);
					aux = aux->prox;
				}
			}
		}
	}

}

void obterLocalidadeTemporal(FILE **arq, ListaChunk *L) {

	ListaChunk LT;
	criarListaChunk(&LT);
	PChunk aux = L->Primeiro->prox;
	int prim = 1;
	int indice = 1;
	while (aux != NULL)
	{
		char *buffer = (char*) malloc(sizeof(char)*MAX_BUFFER);
		PChunk chunk =  get(LT,aux->itemChunk.idVideo, aux->itemChunk.indiceChunk);

		if(chunk == NULL) {
			inserirChunk(&LT,aux->itemChunk.idVideo, aux->itemChunk.indiceChunk, aux->itemChunk.tamanhoChunk, LT.size  + 1);
		} else {
			decrementarPosicao(&LT,chunk->itemChunk.auxValor+1);

			if(prim) {
				snprintf(buffer,MAX_BUFFER, "%d", LT.size - chunk->itemChunk.auxValor);
				prim = 0;
			} else {
				snprintf(buffer, MAX_BUFFER,",%d", LT.size - chunk->itemChunk.auxValor);
			}

			chunk->itemChunk.auxValor = LT.size;
			escreverNoArquivo(arq,buffer);
			free(buffer);
		}

		aux = aux->prox;
		indice++;
	}
}

void obterPopularidade(FILE **arq, ListaChunk *L) {

	ListaChunk LT;
	criarListaChunk(&LT);
	PChunk aux = L->Primeiro->prox;
	int tam = 0;
	while (aux != NULL)	{
		PChunk chunk =  get(LT,aux->itemChunk.idVideo, aux->itemChunk.indiceChunk);
		if(chunk == NULL) {
			if(aux->itemChunk.idVideo != 0) {
				inserirChunk(&LT,aux->itemChunk.idVideo, aux->itemChunk.indiceChunk, aux->itemChunk.tamanhoChunk, 1);
				tam++;
			}
		} else {
			chunk->itemChunk.auxValor = chunk->itemChunk.auxValor + 1;
		}
		aux = aux->prox;
	}
	ItemChunk *itens = insertionSort(LT, tam);
	int prim = 1;
	int i;
	for(i=0;i<tam;i++) {
		char buffer[MAX_BUFFER];
		if(prim)
			snprintf(buffer,MAX_BUFFER,"%ld %ld %d", itens[i].idVideo, itens[i].indiceChunk, itens[i].auxValor);
		else
			snprintf(buffer,MAX_BUFFER,"\n%ld %ld %d", itens[i].idVideo, itens[i].indiceChunk, itens[i].auxValor);
		escreverNoArquivo(arq, buffer);
	}
}


int main(int argc, char *argv[]) {

	ListaChunk L;
	ListaString T;
	criarListaChunk(&L);
	criarListaString(&T);


	char *nomeArquivo = argv[1];

	preencherChunks(&L, nomeArquivo);

	FILE *arqTemporal = NULL;
	abrirArquivo(&arqTemporal,"localidadetemporal.txt", ESCRITA);
	obterLocalidadeTemporal(&arqTemporal, &L);
	fecharArquivo(&arqTemporal);
	
	FILE *arqEspacial = NULL;
	abrirArquivo(&arqEspacial,"localidadeespacial.txt", ESCRITA);
	obterLocalidadeEspacial(&arqEspacial, &L);
	fecharArquivo(&arqEspacial);

	FILE *arqPopularidade = NULL;
	abrirArquivo(&arqPopularidade,"popularidade.txt", ESCRITA);
	obterPopularidade(&arqPopularidade, &L);
	fecharArquivo(&arqPopularidade);
	
	return 0;
}
